/*
Proxy 用于修改某些操作的默认行为，等同于在语言层面做出修改，所以属于一种“元编程”（meta programming），即对编程语言进行编程。
Proxy 可以理解成，在目标对象之前架设一层“拦截”，外界对该对象的访问，都必须先通过这层拦截，因此提供了一种机制，
可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理，用在这里表示由它来“代理”某些操作，可以译为“代理器”。
*/
var obj = new Proxy({}, {
    get: function (target, propKey, receiver) {
        console.log(`getting ${propKey}!`);
        return Reflect.get(target, propKey, receiver);
    },
    set: function (target, propKey, value, receiver) {
        console.log(`setting ${propKey}!`);
        return Reflect.set(target, propKey, value, receiver);
    }
});//创建了一个{}空对象 里面重写了get和set方法作为拦截
//get 拦截读取 set 拦截更改
//var proxy = new Proxy(target, handler);
console.log(obj)//{} 空对象
obj.count = 1
//  setting count!

console.log(++obj.count)
//  getting count!
//  setting count!
//  2


//同一个拦截器函数，可以设置拦截多个操作
var handler = {
    get: function (target, name) {
        if (name === 'prototype') {
            return Object.prototype;
        }
        return 'Hello, ' + name;
    },

    apply: function (target, thisBinding, args) {
        return args[0];
    },

    construct: function (target, args) {
        return { value: args[1] };
    }
};

var fproxy = new Proxy(function (x, y) {
    return x + y;
}, handler);

fproxy(1, 2) // 1 fproxy是一个函数 设置了代理拦截器 传参数走apply拦截
//new Function() 是 JavaScript 中的一个构造函数，它可以实例化一个新的函数对象并返回。
//该函数对象可以使用传递给 new Function() 的字符串参数作为函数体，
//并使用其他传递给它的参数作为函数参数，从而动态创建一个可执行的函数。
new fproxy(1, 2) // {value: 2} new function 相当于走构造器函数 construct拦截器
fproxy.prototype === Object.prototype // true
fproxy.foo === "Hello, foo" // true

/*
Proxy 支持的拦截操作一览，一共 13 种。
    get(target, propKey, receiver)：拦截对象属性的读取，比如proxy.foo和proxy['foo']。
    set(target, propKey, value, receiver)：拦截对象属性的设置，比如proxy.foo = v或proxy['foo'] = v，返回一个布尔值。
    has(target, propKey)：拦截propKey in proxy的操作，返回一个布尔值。
    deleteProperty(target, propKey)：拦截delete proxy[propKey]的操作，返回一个布尔值。
    ownKeys(target)：拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环，返回一个数组。该方法返回目标对象所有自身的属性的属性名，而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
    getOwnPropertyDescriptor(target, propKey)：拦截Object.getOwnPropertyDescriptor(proxy, propKey)，返回属性的描述对象。
    defineProperty(target, propKey, propDesc)：拦截Object.defineProperty(proxy, propKey, propDesc）、Object.defineProperties(proxy, propDescs)，返回一个布尔值。
    preventExtensions(target)：拦截Object.preventExtensions(proxy)，返回一个布尔值。
    getPrototypeOf(target)：拦截Object.getPrototypeOf(proxy)，返回一个对象。
    isExtensible(target)：拦截Object.isExtensible(proxy)，返回一个布尔值。
    setPrototypeOf(target, proto)：拦截Object.setPrototypeOf(proxy, proto)，返回一个布尔值。如果目标对象是函数，那么还有两种额外操作可以拦截。
    apply(target, object, args)：拦截 Proxy 实例作为函数调用的操作，比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
    construct(target, args)：拦截 Proxy 实例作为构造函数调用的操作，比如new proxy(...args)。
*/

